#include "StdAfx.h"
#include "TriangleSpecimen.h"
#include <math.h>
#include <sstream>

TriangleSpecimen::TriangleSpecimen(Point *a, Point *b, Point *c, Random *generator)
:m_a(a), m_b(b), m_c(c), m_generator(generator)
{
}

TriangleSpecimen::~TriangleSpecimen(void)
{
	delete m_a;
	delete m_b;
	delete m_c;
}

ISpecimen * TriangleSpecimen::Crossover(ISpecimen *other)
{
	Point *o_c = dynamic_cast<TriangleSpecimen*>(other)->m_c;
	return new TriangleSpecimen(new Point(m_a->GetX(), m_a->GetY()),
		new Point(m_b->GetX(), m_b->GetY()), new Point(o_c->GetX(), o_c->GetY()), m_generator);
}

ISpecimen* TriangleSpecimen::Mutate()
{
	Point *o_c = new Point(m_generator);
	return new TriangleSpecimen(new Point(m_a->GetX(), m_a->GetY()),
		 new Point(o_c->GetX(), o_c->GetY()), new Point(m_b->GetX(), m_b->GetY()), m_generator);
}

bool TriangleSpecimen::operator <(ISpecimen &rhs)
{
	double cos_lhs;
	double cos_rhs;
	cos_lhs = computeMinCos(*this);
	cos_rhs = computeMinCos(dynamic_cast<TriangleSpecimen&>(rhs));
	
//	std::cout << "cos_lhs = " << cos_lhs << " cos_rhs = " << cos_rhs << "returning: " << (cos_lhs > cos_rhs) << std::endl;
	return cos_lhs < cos_rhs;
}


double TriangleSpecimen::computeCos(Point *apex, Point *handA, Point *handB)
{
	double ux = handA->GetX() - apex->GetX();
	double uy = handA->GetY() - apex->GetY();

	double wx = handB->GetX() - apex->GetX();
	double wy = handB->GetY() - apex->GetY();

	double ul = sqrt(pow(ux, 2) + pow(uy, 2));
	double wl = sqrt(pow(wx, 2) + pow(wy, 2));

	double cos_a = (ux*wx + uy*wy)/(ul*wl);

	return cos_a;
}

double TriangleSpecimen::computeMinCos(TriangleSpecimen &tr)
{
	double cos;
	double cos_tmp;

	cos = abs(computeCos(tr.m_a, tr.m_b, tr.m_c));
	//wierzcholek m_b
	cos_tmp = abs(computeCos(tr.m_b, tr.m_a, tr.m_c));
	cos = cos_tmp < cos ? cos_tmp : cos;
	//wierzcholek m_c
	cos_tmp = abs(computeCos(tr.m_c, tr.m_a, tr.m_b));
	cos = cos_tmp < cos ? cos_tmp : cos;
	
	return cos;
}

std::string TriangleSpecimen::ToString()
{
	std::ostringstream stream;
	stream << "[(" << m_a->GetX() << ", " << m_a->GetY() << "), ";
	stream << "(" << m_b->GetX() << ", " << m_b->GetY() << "), ";
	stream << "(" << m_c->GetX() << ", " << m_c->GetY() << ")] ";
	stream << "cos: " << computeMinCos(*this);
	return stream.str();
}